//-----------------------------------------------------------------------------
// Bend2D - Physics Engine
// Roberto Bender <beto.bender@gmail.com>
// Description: 
// Date: 11/03/2010
//-----------------------------------------------------------------------------
#include "bmath.h"
#include <cmath>
using namespace bend2d;

double Math::pi = 3.14159265;

double Math::ConvertRWToBend2D(double value, eRWConvertType)
{
    return value; 
}

void Math::ConvertToBinary(unsigned int value, unsigned int size, string& retvalue)
{
    stringstream str;

    while(value != 0)
    {
        str << value % 2;
        value = value / 2;
    }

    retvalue = str.str();

    while(retvalue.size() < size)
        retvalue = "0" + retvalue;
}

double Math::CalculateVolume(const Rectangle& rectangle)
{
    // TODO
    return 0;
}

double Math::CalculatePerimeter(const Rectangle& rectangle)
{
    // TODO
    return 0;
}

double Math::Sin(const Angle& angle)
{
    return sin(angle.GetAngle(Angle::eAngleRad));
}

double Math::Cos(const Angle& angle)
{
    return cos(angle.GetAngle(Angle::eAngleRad));
}

void Math::ApplySin(const Angle& angle, double& value)
{
    value = value * sin(angle.GetAngle(Angle::eAngleRad));
}

void Math::ApplyCos(const Angle& angle, double& value)
{
    value = value * cos(angle.GetAngle(Angle::eAngleRad));
}

Angle Math::ArcSin(double value)
{
    Angle angle(asin(value), Angle::eAngleRad);
    return angle;
}

Angle Math::ArcCos(double value)
{
    Angle angle(acos(value), Angle::eAngleRad);
    return angle;
}

Angle Math::ArcTg(double value)
{
    Angle angle(atan(value), Angle::eAngleRad);
    return angle;
}

double Math::Sqrt(double value)
{
    return sqrt(value);
}

double Math::Pow(double value, double p)
{
    return pow(value, p);
}

double Math::Abs(double value)
{
    if(value < 0) return value * -1;
    return value;
}

bool Math::IsIn(const Point& point, const Rectangle& rectangle)
{
// TODO Rectangle Could Not Be Perfect
	return (point.GetX() >= rectangle.GetLeft() && 
			point.GetX() <= rectangle.GetRight() &&
			point.GetY() >= rectangle.GetBottom() &&
			point.GetY() <= rectangle.GetTop());
}

bool Math::Cross(Line& a, Line& b, Point& position, double radius)
{
    a.CalculateVariables();
    b.CalculateVariables();

    double A1 = a.GetAlpha();
    double B1 = a.GetBeta();
    double C1 = a.GetGamma();

    double A2 = b.GetAlpha();
    double B2 = b.GetBeta();
    double C2 = b.GetGamma();
    
    double det = A1*B2 - A2*B1;
    double px = (B2*C1 - B1*C2)/det;
    double py = (A1*C2 - A2*C1)/det;
   
    position = Point(px, py);

    return (py <= a.GetHighY()+radius && py >= a.GetLowY()-radius && px <= a.GetHighX()+radius && px >= a.GetLowX()-radius &&
            py <= b.GetHighY()+radius && py >= b.GetLowY()-radius && px <= b.GetHighX()+radius && px >= b.GetLowX()-radius); 
}

void Math::ConvertLineToPoint(const Line& line, Point& point)
{
    point.SetXY(line.GetFrom().GetX() - line.GetTo().GetX(),
                line.GetFrom().GetY() - line.GetTo().GetY());
}
